﻿using System.Collections.Generic;
using System;

namespace EventBus2
{
    public class EventBus
    {
        private static EventBus _default;
        protected static readonly object locker = new object();
        private Dictionary<Type, List<Action<object, MyEventArgs>>> eventDic = new Dictionary<Type, List<Action<object, MyEventArgs>>>();
        public static EventBus Default
        {
            get
            {
                if (_default == null)
                {
                    lock (locker)
                    {
                        // 如果类的实例不存在则创建，否则直接返回
                        if (_default == null)
                        {
                            _default = new EventBus();
                        }
                    }
                }
                return _default;
            }
        }

        /// <summary>
        /// 订阅
        /// </summary>
        /// <typeparam name="T">订阅的时候，就应该知道订阅什么事件</typeparam>
        /// <param name="eventHandler">事件发生时执行的handler,object是发送者，</param>
        public void Subscribe<T>(Action<object, MyEventArgs> eventHandler) where T : IEvent
        {
            lock (locker)
            {
                if (eventDic.ContainsKey(typeof(T)))
                {
                    eventDic[typeof(T)].Add(eventHandler);
                }
                else
                {
                    eventDic.Add(typeof(T), new List<Action<object, MyEventArgs>>() { eventHandler });
                }
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="eventHandler"></param>
        public void Unsubscribe<T>(Action<object, MyEventArgs> eventHandler) where T : IEvent
        {
            lock (locker)
            {
                if (eventDic.ContainsKey(typeof(T)) && eventDic[typeof(T)].Contains(eventHandler))
                {
                    eventDic[typeof(T)].Remove(eventHandler);
                }
            }
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="e">发布的时候，应该是发布具体的事件，而不是事件类型</param>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        public virtual void Publish(IEvent e, object sender, MyEventArgs eventArgs)
        {
            lock (locker)
            {
                if (eventDic.ContainsKey(e.GetType()))
                {
                    var subscriptions = eventDic[e.GetType()];
                    for (int i = 0; i < subscriptions.Count; i++)
                    {
                        subscriptions[i](sender, eventArgs);
                    }
                }

            }
        }
    }
}
